using System;
using System.Collections.Generic;
using System.Text;
using System.DirectoryServices;
using Suucha.Adsi;

namespace Suucha.AdHelper
{
    public sealed class OUHelper
    {
        public static OUInfo GetOUInfo(string name, bool getChildren, bool getUsers)
        {
            DirectoryEntry de = AdsiCommon.GetDirectoryEntry(Common.ADPath, Common.UserName, Common.Password);
            DirectorySearcher ds = AdsiCommon.GetDirectorySearcher(de);
            ds.Filter = "(&(objectClass=organizationalUnit)(name=" + name + "))";
            OUInfo ouInfo;
            try
            {
                SearchResult result = ds.FindOne();
                ouInfo = GetOUInfoByPath(result.Path);
                ouInfo = GetUserAndChild(getChildren, getUsers, ouInfo, result);
            }
            catch
            {
                ouInfo = new OUInfo();
            }
            return ouInfo;
        }

        private static OUInfo GetUserAndChild(bool getChildren, bool getUsers, OUInfo ouInfo, SearchResult result)
        {
            if (getChildren)
            {
                ouInfo.Children = GetChildren(result.Path);
                for (int i = 0; i < ouInfo.Children.Count; i++)
                {
                    ouInfo.Children[i].Parent = ouInfo;
                }
            }
            if (getUsers)
            {
                ouInfo.Users = GetUsers(result.Path);
                for (int i = 0; i < ouInfo.Users.Count; i++)
                    ouInfo.Users[i].Ou = ouInfo;
            }
            return ouInfo;
        }
        public static List<OUInfo> Search()
        {

            List<OUInfo> ous = new List<OUInfo>();
            DirectorySearcher ds = AdsiCommon.GetDirectorySearcher(Common.ADPath, Common.UserName, Common.Password);
            ds.Filter = "(&(objectClass=organizationalUnit))";
            try
            {
                SearchResultCollection results = ds.FindAll();
                foreach (SearchResult result in results)
                {
                    OUInfo ou = GetOUInfoByPath(result.Path);
                    ous.Add(ou);
                }

            }
            catch
            {
            }
            return ous;

        }
        public static OUInfo GetOUInfo(Guid ouId, bool getChildren, bool getUsers)
        {
            DirectorySearcher ds = AdsiCommon.GetDirectorySearcher(Common.ADPath, Common.UserName, Common.Password);
            ds.Filter = "(&(objectClass=organizationalUnit)(objectGUID=" + Common.Guid2OctetString(ouId) + "))";
            OUInfo ouInfo = new OUInfo();
            try
            {
                SearchResultCollection results = ds.FindAll();
                foreach (SearchResult result in results)
                {
                    Guid guid = Common.GetGuid(result);
                    if (guid == ouId)
                    {
                        ouInfo = GetOUInfoByPath(result.Path);
                        ouInfo = GetUserAndChild(getChildren, getUsers, ouInfo, result);
                        break;
                    }
                }
            }
            catch
            {
            }
            return ouInfo;
        }

        internal static OUInfo GetOUInfoByPath(string path)
        {
            DirectoryEntry ou = AdsiCommon.GetDirectoryEntry(path, Common.UserName, Common.Password);
            OUInfo ouInfo = FillOUInfo(ou);
            return ouInfo;
        }

        private static List<OUInfo> GetChildren(string path)
        {
            List<OUInfo> children = new List<OUInfo>();
            DirectoryEntry parent = AdsiCommon.GetDirectoryEntry(path, Common.UserName, Common.Password);
            foreach (DirectoryEntry child in parent.Children)
            {
                if (child.SchemaClassName == "organizationalUnit")
                {
                    OUInfo info = FillOUInfo(child);
                    children.Add(info);
                }
            }
            return children;
        }

        private static List<UserInfo> GetUsers(string path)
        {
            List<UserInfo> user = new List<UserInfo>();
            DirectoryEntry parent = AdsiCommon.GetDirectoryEntry(path, Common.UserName, Common.Password);
            foreach (DirectoryEntry child in parent.Children)
            {
                if (child.SchemaClassName == "user")
                {
                    //UserInfo info = new UserInfo();
                    //info.Id = child.Guid;
                    UserInfo info = UserHelper.FillUserInfoOnly(child);
                    user.Add(info);
                }
            }
            return user;
        }

        private static OUInfo FillOUInfo(DirectoryEntry ou)
        {
            OUInfo ouInfo = new OUInfo();
            ouInfo.Id = ou.Guid;
            ouInfo.Name = (string)ou.Properties["name"].Value;
            if (ou.Parent.SchemaClassName == "organizationalUnit")
            {
                ouInfo.Parent = new OUInfo();
                ouInfo.Parent = GetOUInfoByPath(ou.Parent.Path);
            }
            return ouInfo;
        }
    }
}
